Первая программа на JavaServer Faces
Первая программа на JavaServer Faces
JavaServer Faces (JSF) представляет собой стандартный фреймворк для создания веб-приложений на платформе Java Enterprise Edition. Фреймворк реализует паттерн Model-View-Controller (MVC), обеспечивая разделение логики приложения, пользовательского интерфейса и управления состоянием. Взаимодействие с JSF происходит через сервлеты, которые обрабатывают входящие HTTP-запросы и передают управление компонентам интерфейса. Создание первой программы позволяет познакомиться с жизненным циклом запроса, работой управляемых bean, валидацией данных и навигацией между страницами.
Создание проекта
Для начала работы требуется среда выполнения Java (JDK) версии 8 или выше и сервер приложений, поддерживающий спецификацию Servlet и JSP, например Apache Tomcat. Также необходим инструмент сборки проектов, такой как Maven или Gradle.
Процесс инициализации нового проекта выполняется через консольную утилиту или IDE. Система автоматически создаст структуру папок, настроит зависимости и файлы конфигурации.
# Установка Maven (если не установлен)
mvn -version
# Создание проекта Maven с архетипом JSF
mvn archetype:generate \
-DgroupId=com.example \
-DartifactId=my-first-jsf-app \
-DarchetypeArtifactId=maven-archetype-webapp \
-DinteractiveMode=false
cd my-first-jsf-app
После создания структуры необходимо добавить зависимости в файл pom.xml. Основные библиотеки включают сам фреймворк JSF (например, Mojarra или MyFaces), библиотеку для стилей (например, PrimeFaces или OmniFaces) и API сервлетов.
<dependencies>
<!-- API для Java Server Faces -->
<dependency>
<groupId>jakarta.faces</groupId>
<artifactId>jakarta.faces-api</artifactId>
<version>3.0.0</version>
<scope>provided</scope>
</dependency>
<!-- Реализация JSF (Mojarra) -->
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>jakarta.faces</artifactId>
<version>3.0.0</version>
</dependency>
<!-- API для Servlets -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>5.0.0</version>
<scope>provided</scope>
</dependency>
<!-- Библиотека для красивых компонентов (PrimeFaces) -->
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>12.0.0</version>
</dependency>
</dependencies>
Файл web.xml содержит конфигурацию фронтенда-сервлета (FacesServlet), который перехватывает все запросы к ресурсам с расширением .xhtml.
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0">
<display-name>My First JSF App</display-name>
<!-- Настройка FacesServlet -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>jakarta.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
</web-app>
Запуск сервера осуществляется командой mvn tomcat7:run (при наличии плагина) или копированием артефакта WAR в директорию webapps сервера Tomcat. Приложение становится доступным по адресу http://localhost:8080/my-first-jsf-app/.
Управляемый Bean (Managed Bean)
Управляемые bean представляют собой классы Java, которые инкапсулируют состояние и логику представления. Они становятся доступны в контексте страницы и могут быть использованы для хранения данных формы, обработки событий и навигации.
Создадим класс CounterBean, который будет управлять счетчиком и текстом ввода. Класс помечается аннотацией @Named, чтобы его можно было найти по имени в Expression Language (EL). Аннотация @RequestScoped указывает, что экземпляр класса создается при каждом запросе и уничтожается после его завершения.
package com.example.bean;
import jakarta.annotation.PostConstruct;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.inject.Named;
import java.io.Serializable;
@Named("counterBean")
@RequestScoped
public class CounterBean implements Serializable {
private static final long serialVersionUID = 1L;
private int count;
private String name;
private String message;
@PostConstruct
public void init() {
this.count = 0;
this.name = "";
this.message = "Добро пожаловать!";
}
public void increment() {
count++;
}
public void decrement() {
if (count > 0) {
count--;
}
}
public void reset() {
count = 0;
message = "Счетчик сброшен.";
}
public void validateName(FacesContext context) {
if (name == null || name.trim().isEmpty()) {
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
"Ошибка", "Имя не может быть пустым"));
} else {
message = "Привет, " + name + "!";
}
}
// Геттеры и сеттеры
public int getCount() { return count; }
public void setCount(int count) { this.count = count; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
}
Метод @PostConstruct вызывается сразу после создания экземпляра бина для инициализации значений. Методы increment, decrement и reset изменяют состояние объекта. Метод validateName демонстрирует работу с объектом FacesContext для добавления сообщений об ошибках или успехах. Тип Serializable обязателен для сохранения состояния между запросами при использовании определенных режимов скроллинга.
Страница представления (XHTML)
Страница представления пишется на языке XML с использованием тегов из пространства имен JSF. Расширение файлов должно быть .xhtml. Фреймворк парсит этот файл и преобразует его в HTML, который отправляется браузеру.
Создадим файл index.xhtml в директории src/main/webapp.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Первая программа на JSF</title>
<h:outputStylesheet library="css" name="style.css"/>
</h:head>
<h:body>
<div class="container">
<h:form id="mainForm">
<h1>Моя первая программа на JSF</h1>
<!-- Блок с приветствием -->
<div class="greeting">
<h:panelGroup rendered="#{not empty counterBean.name}">
<p style="color: green;">#{counterBean.message}</p>
</h:panelGroup>
<h:inputText value="#{counterBean.name}"
placeholder="Введите ваше имя"
required="true"
requiredMessage="Поле имя обязательно для заполнения">
<f:ajax event="blur" listener="#{counterBean.validateName}" />
</h:inputText>
<h:message for="mainForm:name" style="color: red;" />
</div>
<!-- Блок со счетчиком -->
<div class="counter">
<h2>Счетчик: #{counterBean.count}</h2>
<div class="buttons">
<h:commandButton value="-" action="#{counterBean.decrement}" />
<h:commandButton value="Сброс" action="#{counterBean.reset}" />
<h:commandButton value="+" action="#{counterBean.increment}" />
</div>
</div>
<!-- Сообщения о событиях -->
<h:messages globalOnly="false" layout="list" />
</h:form>
</div>
</h:body>
</html>
Теги <h:> принадлежат пространству имен HTML JSF. Тег <h:form> оборачивает компоненты, требующие отправки данных на сервер. Атрибут value связывает компонент ввода с свойством бина (counterBean.name). Атрибут action вызывает метод бина при клике на кнопку. Директива rendered управляет видимостью блока в зависимости от условия. Тег <f:ajax> обеспечивает частичную перезагрузку страницы при событии blur (потеря фокуса), вызывая метод валидации без полной перерисовки.
Стили оформления
Внешний вид приложения задается файлом CSS. Файлы стилей размещаются в директории src/main/webapp/css и подключаются через тег <h:outputStylesheet>.
.container {
text-align: center;
padding: 40px;
font-family: Arial, sans-serif;
max-width: 600px;
margin: 0 auto;
}
.greeting {
margin: 30px 0;
padding: 20px;
background: #f0f0f0;
border-radius: 10px;
border: 1px solid #ddd;
}
.counter {
margin: 30px 0;
padding: 20px;
background: #e8f4f8;
border-radius: 10px;
border: 1px solid #b3d9ff;
}
.buttons {
margin-top: 15px;
}
h1 {
color: #333;
}
h2 {
font-size: 1.5em;
color: #0056b3;
}
/* Стилизация кнопок */
.ui-button {
margin: 0 5px;
padding: 10px 20px;
font-size: 16px;
background: #42b883; /* Цвет JSF/PrimeFaces */
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
transition: 0.3s;
}
.ui-button:hover {
background: #3aa876;
transform: scale(1.05);
}
input[type="text"] {
padding: 10px;
font-size: 16px;
border: 2px solid #ddd;
border-radius: 5px;
width: 200px;
margin-right: 10px;
}
CSS правила определяют расположение элементов, цвета и поведение при взаимодействии. Классы .ui-button применяются к кнопкам, генерируемым библиотекой PrimeFaces. Атрибут transform: scale(1.05) создает эффект увеличения кнопки при наведении курсора.
Жизненный цикл запроса JSF
Приложение демонстрирует фундаментальные принципы работы фреймворка. Запрос проходит несколько этапов: восстановление состояния (Restore View), обработка входных данных (Process Validations), обновление модели (Update Model Values), вызов слушателей (Invoke Application) и рендеринг ответа (Render Response).
Восстановление состояния — это этап, на котором фреймворк восстанавливает дерево компонентов из предыдущего запроса или создает новое дерево. Данные из формы сохраняются во временном хранилище.
Обработка входных данных включает валидацию введенных пользователем значений. Если данные не соответствуют требованиям (например, пустое поле), генерируется сообщение об ошибке, и дальнейшая обработка блокируется.
Вызов слушателей активирует методы, указанные в атрибутах action. Эти методы могут изменять состояние приложения и определять результат навигации.
Рендеринг ответа формирует итоговый HTML-документ, который отправляется клиентскому браузеру. При использовании AJAX часть страницы обновляется динамически без перезагрузки всей страницы.
Навигация
Навигация в JSF определяет переход пользователя между страницами после выполнения действий. Конфигурация может осуществляться через файл faces-config.xml или аннотации в коде.
Пример использования аннотации @NavigationCase в методе бина:
public String navigateToResult() {
// Логика обработки
return "result"; // Возвращаем логическое имя страницы
}
В файле faces-config.xml:
<navigation-rule>
<from-view-id>/index.xhtml</from-view-id>
<navigation-case>
<from-outcome>result</from-outcome>
<to-view-id>/result.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
Альтернативный подход — использование выражений в return внутри метода, которые указывают путь к странице напрямую, если используется конфигурация по умолчанию.
Расширение функционала
Полученное приложение служит базой для дальнейших экспериментов. Разработчики могут добавлять новые функции, изучая механизмы работы с данными и интерфейсом.
Добавление таблицы со списком задач предполагает использование компонента <p:dataTable> из библиотеки PrimeFaces. Данные передаются через список объектов, хранящихся в бине.
Реализация календаря требует подключения компонента <p:calendar> и настройки формата даты. Значение даты сохраняется в свойстве типа Date или LocalDate.
Интеграция с базой данных осуществляется через внедрение сущностей JPA или использование сервисного слоя для доступа к данным. Бин получает данные из сервиса и передает их в представление.
Пошаговый запуск
Для успешного запуска приложения необходимо выполнить последовательность действий.
- Установите JDK версии 8 или выше с официального сайта oracle.com или adoptium.net.
- Откройте терминал или командную строку.
- Установите Maven, если он еще не установлен.
- Создайте проект Maven с помощью команды
mvn archetype:generate. - Добавьте зависимости в файл
pom.xml. - Создайте управляемый бин в пакете
com.example.bean. - Создайте страницу
index.xhtmlв директорииsrc/main/webapp. - Добавьте файл стилей
style.cssв директориюsrc/main/webapp/css. - Настройте файл
web.xmlдля регистрации FacesServlet. - Запустите сервер приложений (Tomcat) и перейдите по адресу
http://localhost:8080/my-first-jsf-app/.
Браузер автоматически откроет страницу приложения. Любые изменения в коде сохраняются и мгновенно отображаются на странице после перезапуска сервера.
Рекомендации по развитию
JSF предоставляет мощный инструментарий для построения сложных корпоративных интерфейсов. Автоматическая обработка состояний и событий гарантирует актуальность данных на экране. Компонентная архитектура позволяет строить большие системы из небольших, понятных частей.
Использование библиотек компонентов, таких как PrimeFaces или RichFaces, значительно ускоряет разработку и улучшает внешний вид приложений. Эти библиотеки предоставляют готовые решения для таблиц, форм, графиков и других сложных элементов интерфейса.
Экспериментируйте с кодом, меняйте стили, добавляйте новые состояния и функции. Практика является лучшим способом усвоения материала.